"""
@Author：WangYuXiang
@E-mile：Hill@3io.cc
@CreateTime：2021/4/12 17:41
@DependencyLibrary：无
@MainFunction：无
@FileDoc： 
    permission.py
    文件说明
@ChangeHistory:
    datetime action why
    example:
    2021/4/12 17:41 change 'Fix bug'
        
"""
from typing import List, Any

from common.auth.models import PermissionModel, GroupModel, RoleModel
from common.auth.serializers import PermissionModelSerializer, PermissionHandlePostSerializer, PermissionHandleGetSerializer
from common.utils.authentication import GeneralTokenAuthenticate
from common.utils.site_views import AdminSiteView
from sanic_rest_framework.exceptions import APIException
from sanic_rest_framework.views import GeneralView


class PermissionViewSet(AdminSiteView):
    lookup_field = 'code'
    queryset = PermissionModel
    serializer_class = PermissionModelSerializer
    authentication_classes = (GeneralTokenAuthenticate,)
    search_fields = ('@code', '@name')


class PermissionHandleView(GeneralView):
    authentication_classes = (GeneralTokenAuthenticate,)

    async def post(self, request, *args, **kwargs):
        phs = PermissionHandlePostSerializer(data=request.data)
        await phs.is_valid(raise_exception=True)
        add_perms = phs.validated_data.pop('add_perm', None)
        delete_perms = phs.validated_data.pop('delete_perm', None)
        obj = await self.get_object(**phs.validated_data)
        for i in add_perms:
            await obj.permissions.add(i)
        for i in delete_perms:
            if await obj.permissions.filter(code=i.code).exists():
                await obj.permissions.remove(i)

        return self.success_json_response()

    async def get(self, request, *args, **kwargs):
        phs = PermissionHandleGetSerializer(data=request.args)
        await phs.is_valid(raise_exception=True)

        obj = await self.get_object(**phs.validated_data)
        if obj is None:
            return self.error_json_response(msg='正在请求不存在的组织机构数据')
        permissions = await self.handle_permission(obj)
        return self.success_json_response(permissions)

    async def get_object(self, model_type: str, pk):
        """
        根据 model_type 得到模型
        :param model_type: role or group
        :param pk: 主键
        :return:
        """
        if model_type == 'role':
            return await RoleModel.get_or_none(pk=pk)
        elif model_type == 'group':
            return await GroupModel.get_or_none(pk=pk)
        else:
            raise APIException('出现意料之外的参数：%s' % model_type)

    async def handle_permission(self, role: Any):
        """
        处理权限，组合成前端需要的Json
        :param role:
        :return:
        """
        permissions = {}

        role_permission_codes = self.extract_code(await role.all_permissions())
        role_no_inherit_permission_codes = self.extract_code(await role.all_permissions(is_inherit=False))

        all_permissions = await PermissionModel.all().group_by('classify_code')
        for permission in all_permissions:
            classify_code = permission.classify_code
            classify_name = permission.classify_name
            code = permission.code
            name = permission.name
            has = code in role_permission_codes
            disabled = code not in role_no_inherit_permission_codes and has

            if classify_code not in permissions:
                permissions[classify_code] = {
                    'label': classify_name,
                    'permissions': {}
                }
            permissions[classify_code]['permissions'][code] = {
                'label': name,
                'has': has,
                'disabled': disabled,
                'is_original': has and not disabled
            }
        return permissions

    def extract_code(self, objs: List[PermissionModel]):
        """
        提取权限内的code
        :param objs:
        :return:
        """
        return [i.code for i in objs]
